package com.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;  
  
/**
 * mina
 */
public class MinaHeatServer {  
	
	static Logger LOG = LoggerFactory.getLogger(MinaHeatServer.class);
  
    private static final int PORT = 8013;  
    /** 30秒后超时 */  
    private static final int IDELTIMEOUT = 20;  
    /** 15秒发送一次心跳包 */  
    private static final int HEARTBEATRATE = 7;  
    /** 心跳包内容 */  
    public static final String HEARTBEATREQUEST = "0x11";  
    public static final String HEARTBEATRESPONSE = "0x12";  
  
    public static void main(String[] args) throws IOException {  
        IoAcceptor acceptor = new NioSocketAcceptor();  
        acceptor.getSessionConfig().setReadBufferSize(1024);  
        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,  
                IDELTIMEOUT);  
          
        acceptor.getFilterChain().addLast("logger", new LoggingFilter());  
        acceptor.getFilterChain().addLast(  
                "codec",  
                new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName( "UTF-8" ))));  
  
        KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl();  
        //1.默认方式，检测到超时后关闭session
//        KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory,  IdleStatus.BOTH_IDLE);  
       
        //2.自定义Handler方式  ，检测到超时后关闭session
        KeepAliveRequestTimeoutHandler heartBeatHandler = new  KeepAliveRequestTimeoutHandlerImpl();  
        KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory,  
                IdleStatus.BOTH_IDLE, heartBeatHandler);  
        
        //设置是否forward到下一个filter  
        heartBeat.setForwardEvent(true);  
        //设置心跳频率  
        heartBeat.setRequestInterval(HEARTBEATRATE);  
  
        acceptor.getFilterChain().addLast("heartbeat", heartBeat);  
  
        acceptor.setHandler(new MyIoHandler());  
        acceptor.bind(new InetSocketAddress(PORT));  
        System.out.println("Server started on port： " + PORT);  
    }  
  
    
    /**************************内部类，心跳*******************************************/
    /** 
     * @ClassName KeepAliveMessageFactoryImpl 
     * @Description 内部类，实现KeepAliveMessageFactory（心跳工厂） 
     * @author cruise 
     * 
     */  
    private static class KeepAliveMessageFactoryImpl implements  
            KeepAliveMessageFactory {  
  
        @Override  
        public boolean isRequest(IoSession session, Object message) {  
        	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            LOG.info("请求心跳包信息={}, session={}, time={}", new Object[] {message, session, simpleDateFormat.format(new Date())});
            if (message.equals(HEARTBEATREQUEST))  
                return true;  
            return false;  
        }  
  
        @Override  
        public boolean isResponse(IoSession session, Object message) {  
//          LOG.info("响应心跳包信息: " + message);  
          if(message.equals(HEARTBEATRESPONSE))  
              return true;  
            return false;  
        }  
  
        @Override  
        public Object getRequest(IoSession session) {  
//            LOG.info("请求预设信息: " + HEARTBEATREQUEST);  
            /** 返回预设语句 */  
            return HEARTBEATREQUEST;  
        }  
  
        @Override  
        public Object getResponse(IoSession session, Object request) {  
//            LOG.info("响应预设信息: " + HEARTBEATRESPONSE);  
            /** 返回预设语句 */  
            return HEARTBEATRESPONSE;  
//          return null;  
        }  
  
    }  
      
    /** 
     * 对应上面的注释 
     * KeepAliveFilter(heartBeatFactory,IdleStatus.BOTH_IDLE,heartBeatHandler) 
     * 心跳超时处理 
     * KeepAliveFilter 在没有收到心跳消息的响应时，会报告给的KeepAliveRequestTimeoutHandler。 
     * 默认的处理是 KeepAliveRequestTimeoutHandler.CLOSE 
     * （即如果不给handler参数，则会使用默认的从而Close这个Session） 
     * @author cruise 
     * 
     */  
	private static class KeepAliveRequestTimeoutHandlerImpl implements KeepAliveRequestTimeoutHandler {
		@Override
		public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception {
			MinaHeatServer.LOG.info("HeatServer.keepalive 心跳超时！,session={}", session);
			CLOSE.keepAliveRequestTimedOut(filter, session);
		}

	}
	
	
	/**************************内部类，handler*******************************************/
	private static class MyIoHandler extends IoHandlerAdapter{  
		  
	    @Override  
	    public void sessionOpened(IoSession session) throws Exception {  
	    	super.sessionOpened(session);
	    }  
	  
	    @Override  
	    public void sessionClosed(IoSession session) throws Exception {  
	    	super.sessionClosed(session);
	    }  
	    
	    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
	    	super.exceptionCaught(session,cause);
	    }
	  
	    @Override  
	    public void messageReceived(IoSession session, Object message)  
	            throws Exception {  
	        String ip = session.getRemoteAddress().toString();  
	        System.out.println("===> Message From " + ip + " : " + message);       
	        session.write(ip);
	        session.close(true);
	    }

		@Override
		public void sessionCreated(IoSession session) throws Exception {
			super.sessionCreated(session);
		}

		@Override
		public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
			super.sessionIdle(session, status);
		}

		@Override
		public void messageSent(IoSession session, Object message) throws Exception {
			super.messageSent(session, message);
		}  
	}  
}  